// Triangle.cpp
// Our first OpenGL program that will just draw a triangle on the screen.

#include <stdafx.h>
#include <GLTools.h>            // OpenGL toolkit
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLBatch.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#ifdef __APPLE__
#include <glut/glut.h>          // OS X version of GLUT
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>            // Windows FreeGlut equivalent
#include "triangle.h"
#endif


GLFrame frame;
GLFrame cameraFrame;
GLFrustum frustum;
GLuint shader;
int MVPMatrixLocation;

M3DMatrix44f VPMatrix;
M3DMatrix44f mCamera;
M3DMatrix44f mFrame;


float matrix[16] = {1,0,0,0,
					0,1,0,0,
					0,0,1,0,
					0,0,0,1};
///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.

void ChangeSize(int w, int h) {
    glViewport(0, 0, w, h);
	frustum.SetPerspective(50,w/h,-100,100);
}


void SetUpFrame(GLFrame &frame,const M3DVector3f origin,
				const M3DVector3f forward,
				const M3DVector3f up) {
					frame.SetOrigin(origin);
					frame.SetForwardVector(forward);
M3DVector3f side,oUp;
m3dCrossProduct3(side,forward,up);
m3dCrossProduct3(oUp,side,forward);
frame.SetUpVector(oUp);
frame.Normalize();

}

void LookAt(GLFrame &frame, const M3DVector3f eye,
        const M3DVector3f at,
        const M3DVector3f up) {
    M3DVector3f forward;
    m3dSubtractVectors3(forward, at, eye);
    SetUpFrame(frame, eye, forward, up);
}

///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context.
// This is the first opportunity to do any OpenGL related tasks.

void SetupRC() {
	

    // Blue background
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

    shader = gltLoadShaderPairWithAttributes("vshader.vp", "fshader.fp",
            2, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_COLOR, "vColor");
    fprintf(stdout, "GLT_ATTRIBUTE_VERTEX : %d\nGLT_ATTRIBUTE_COLOR : %d \n",
            GLT_ATTRIBUTE_VERTEX, GLT_ATTRIBUTE_COLOR);


	MVPMatrixLocation=glGetUniformLocation(shader,"MVPMatrix");
	if(MVPMatrixLocation==-1)
	{
		fprintf(stderr,"uniform MVPMatrix could not be found\n");
	}
/*	frame.SetForwardVector(0.f,0.f,-1.f);
	frame.SetUpVector(0.f,1.f,0.f);
	frame.SetOrigin(0.f,0.f,0.f);*/
	M3DVector3f o = {0.f,0.f,0.f };
	M3DVector3f f = {0.f,0.f,-1.f };
	M3DVector3f u = {0.f,1.f,0.f};
	SetUpFrame(frame,o,f,u);

	M3DMatrix44f mCamera;
	cameraFrame.GetCameraMatrix(mCamera);
	glFrontFace(GL_CCW); 
	glEnable( GL_DEPTH_TEST );

/*
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
*/

}

///////////////////////////////////////////////////////////////////////////////
// Called to draw scene

void RenderScene(void) {
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

   
    glUseProgram(shader);

	cameraFrame.GetCameraMatrix(mCamera);
	frame.GetMatrix(mFrame);
	m3dMatrixMultiply44(VPMatrix,mFrame,mCamera);

	//GetProjectionMatrix(GLFloat *);
	glUniformMatrix4fv(MVPMatrixLocation,1,GL_FALSE,VPMatrix);

	//glUniformMatrix4fv(MVPMatrixLocation,1,GL_FALSE,matrix);

    glBegin(GL_TRIANGLES);

	static float scale =0.25f;


	/////////podstawa
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.0, 1.0, 0.0);
	glVertex3f(scale * -0.5f,scale * -0.5f,scale *.0f);
    glVertex3f(scale *-0.5f,scale * 0.5f, scale *0.0);
    glVertex3f(scale *0.5f,scale * -0.5f,scale * .0f);

	glVertex3f(scale * 0.5f,scale * 0.5f,scale *.0f);
    glVertex3f(scale *-0.5f,scale * 0.5f, scale *0.0);
    glVertex3f(scale *0.5f,scale * -0.5f,scale * .0f);
	//// koniec podstawa
	///gorna
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 1.0, 0.0, 0.0);
	glVertex3f(scale * 0.5f,scale * 0.5f,scale *.0f);
    glVertex3f(scale *-0.5f,scale * 0.5f, scale *0.0);
    glVertex3f(scale *0.f,scale * 0.f,scale * 2.0f);


	///prawa
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.0, 0.5, .5);
	glVertex3f(scale * 0.5f,scale * 0.5f,scale *.0f);
    glVertex3f(scale *0.5f,scale * -0.5f, scale *0.0);
    glVertex3f(scale *0.f,scale * 0.f,scale * 2.0f);

	///dolna
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 0.5, 0.5, .5);
	glVertex3f(scale * -0.5f,scale * -0.5f,scale *.0f);
    glVertex3f(scale *0.5f,scale * -0.5f, scale *0.0);
    glVertex3f(scale *0.f,scale * 0.f,scale * 2.0f);


	///lewa
	glVertexAttrib3f(GLT_ATTRIBUTE_COLOR, 1, 1, .5);
	glVertex3f(scale * -0.5f,scale * -0.5f,scale *.0f);
    glVertex3f(scale *-0.5f,scale * 0.5f, scale *0.0);
    glVertex3f(scale *0.f,scale * 0.f,scale * 2.0f);

    glEnd();

    // Perform the buffer swap to display back buffer
    glutSwapBuffers();

	cameraFrame.RotateLocalZ(0.01);
	cameraFrame.RotateLocalY(0.01);
	cameraFrame.RotateLocalX(0.02);
glutPostRedisplay();
}


///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs

int main(int argc, char* argv[]) {
  

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Triangle");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();

    glutMainLoop();
    return 0;
}

triangle::triangle(void)
{
}
